#pragma once

#include <crane/defs.hpp>
#include <crane/core/smart_ptr.hpp>
#include <crane/core/error.hpp>


CRANE_NS_BEGIN
namespace aio {

struct ReactorImpl;

struct ReactorOps {
    static const int OpNone     = 0;
    static const int OpRead     = 1;
    static const int OpWrite    = 2;
    static const int OpError    = 4;
    static const int OpTimeout  = 8;
};

struct IReactorCallback {
    virtual ~IReactorCallback() = default;

    virtual void onEvent(int ops) = 0;
}; // IReactorCallacks

class Reactor {
public:
    struct Timer;

private:
    Reactor() {}
    ~Reactor() {}

    void init(Error & err);
    void add(fd_t fd, int events, IReactorCallback *cb, Error & err);
    void modify(fd_t fd, int events, IReactorCallback * cb, Error & err);
    void remove(fd_t fd, Error & err);
    
    Timer * createTimer(int64_t expiry, IReactorCallback *cb, Error & err);
    void    cancelTimer(Timer * timer, Error & err);
    
    void wait(Error & err);
    void wait(int ms, Error & err);

private:
    SmartPtr<ReactorImpl> m_impl;
}; // ReactorImpl


} // namespace aio
CRANE_NS_END

#ifdef __linux__
#include "impl/epoll_reactor.hpp"
#endif // __linux__
